package com.caocaog.market.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jeecg.common.api.vo.Result;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 中午打印机工具类
 *
 * @author chechen
 * @date 2022-01-19
 * @see <a href="http://open.zhongwu.co/">中午开放平台</a>
 */
public class ZwPrinterUtil {

    private ZwPrinterUtil() {}

    /** 开发者ID */
    private static final Integer APP_ID = 8000761;
    /** 开发者密钥 */
    private static final String APP_SECRET = "41c70a81dc019bb000be89055a2d9c4c";

    private static final String PRINT_URL = "http://api.zhongwuyun.com/";
    private static final String PRINT_STATUS_URL = "http://api.zhongwuyun.com/status";

    public static void print(String orderInfo, String deviceId, String deviceSecret) {
        //时间戳
        int time = Math.round(System.currentTimeMillis()/1000);
        //打印内容
        /*String deviceId = "12407965";
        String deviceSecret = "cdjqqyh5";*/
        String sign = getSign(deviceId, deviceSecret, orderInfo, time);
        System.out.println("time："+time);
        System.out.println("url："+ percentEncode(orderInfo));
        System.out.println("sign："+sign);
        //请求数据
        String datas = "appid="+APP_ID+"&sign="+sign+"&timestamp="+time+"&deviceid="+
                deviceId+"&devicesecret="+deviceSecret+"&printdata="+percentEncode(orderInfo);
        System.out.println(datas);
        try {
            sendPost(PRINT_URL, datas);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Result<String> getStatus(String deviceId, String deviceSecret) {
        int time = Math.round(System.currentTimeMillis()/1000);
        String sign = getSign(deviceId, deviceSecret, null, time);
        //请求数据
        String datas = "appid="+APP_ID+"&sign="+sign+"&timestamp="+time+"&deviceid="+
                deviceId+"&devicesecret="+deviceSecret;
        System.out.println(datas);
        try {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //构建post请求
            HttpGet httpGet = new HttpGet(PRINT_STATUS_URL + "?" + datas);
            //设置请求头
            httpGet.setHeader("Content-type","application/x-www-form-urlencoded");
            // 构建消息实体
            StringEntity entity = new StringEntity(datas, Charset.forName("UTF-8"));
            //entity.setContentType("application/x-www-form-urlencoded");//设置请求头
            entity.setContentEncoding("UTF-8");
            //发送
            CloseableHttpResponse response = httpClient.execute(httpGet);
            //请求成功
            if(response.getStatusLine().getStatusCode() == 200) {
                if(entity != null) {
                    String str = EntityUtils.toString(response.getEntity());
                    //解析返回的数据
                    JSONObject json = JSONObject.parseObject(str);
                    //获取返回的errNum
                    Integer errNum = json.getInteger("errNum");
                    System.out.println("errMsg："+json.getString("errMsg"));
                    if (errNum == 0) {
                        String status = json.getJSONObject("retData").getString("status");
                        if ("0".equals(status)) {
                            return Result.OK("离线");
                        } else if ("1".equals(status)) {
                            return Result.OK("在线");
                        } else if ("2".equals(status)) {
                            return Result.OK("缺纸");
                        }
                    }
                    return Result.error(null, json.getString("errMsg"));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.error(null, "获取失败");
    }

    /**
     * 获取签名
     */
    public static String getSign(String deviceId, String deviceSecret, String printData, int timestamp) {
        String sign = "appid" + APP_ID
                + "deviceid" + deviceId
                + "devicesecret"+ deviceSecret;
        if (StringUtils.isNotBlank(printData)) {
            sign = sign + "printdata" + printData;
        }
        sign = sign + "timestamp" + timestamp
                + APP_SECRET;
        sign = encodeToHex(sign);
        return sign;
    }
    /**
     * 发送数据转码
     * @param s
     * @return
     */
    public static String percentEncode(String s) {
        if (s == null) {
            return "";
        }
        try {
            return URLEncoder.encode(s, "UTF-8")
                    // OAuth encodes some characters differently:
                    .replace("*", "%2A")
                    .replace("%7E", "~");
            // This could be done faster with more hand-crafted code.
        } catch (UnsupportedEncodingException wow) {
            throw new RuntimeException(wow.getMessage(), wow);
        }
    }
    /**
     * 发送post
     * @param url 请求url
     * @param datas 请求数据
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static boolean sendPost(String url,String datas) throws ClientProtocolException, IOException {
        boolean flag = false;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //构建post请求
        HttpPost post = new HttpPost(url);
        //设置请求头
        post.setHeader("Content-type","application/x-www-form-urlencoded");
        // 构建消息实体
        StringEntity entity = new StringEntity(datas, Charset.forName("UTF-8"));
        //entity.setContentType("application/x-www-form-urlencoded");//设置请求头
        entity.setContentEncoding("UTF-8");
        post.setEntity(entity);
        //发送
        CloseableHttpResponse response = httpClient.execute(post);
        //请求成功
        if(response.getStatusLine().getStatusCode() == 200) {
            if(entity != null) {
                String str = EntityUtils.toString(response.getEntity());
                //解析返回的数据
                JSONObject json = JSONObject.parseObject(str);
                //获取返回的retMsg
                //String retMsg = json.getString("retMsg");
                System.out.println("errMsg："+json.getString("errMsg"));
                if (json.containsKey("retData")) {
                    System.out.println("retData："+json.getString("retData"));
                }
                flag = true;
            }
        } else {
            System.out.println("请求失败");
        }
        return flag;
    }

    /**
     * @Title: encodeToBytes
     * @Description: 将源字符串通过MD5进行加密为字节数组
     * @param source 源字符串
     * @return byte[] 通过MD5进行加密后的字节数组
     */
    public static byte[] encodeToBytes(String source) {
        byte[] result = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 重置
            md.reset();
            // 添加需要加密的源
            md.update(source.getBytes("UTF-8"));
            // 加密
            result = md.digest();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 将源字符串通过MD5加密成32位16进制数
     * @param source 源字符
     * @return 通过MD5加密成32位16进制数后的字符串
     */
    public static String encodeToHex(String source) {
        // 先加密为字节数组
        byte[] data = encodeToBytes(source);
        StringBuffer hexSb = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            String hex = Integer.toHexString(0xff & data[i]);
            if (hex.length() == 1) {
                hexSb.append("0");
            }
            hexSb.append(hex);
        }
        return hexSb.toString();
    }

    /**
     * 验证字符串是否匹配
     * @param unknown 待验证的字符串
     * @param okHex   使用MD5加密后的16进制字符串
     * @return 是否匹配
     */
    public static boolean validate(String unknown, String okHex) {
        return okHex.equals(encodeToHex(unknown));
    }

}
